﻿using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using AppFramework.DinosaursParkMes.MaterialModel;
using AppFramework.DinosaursParkMes.Product;
using AppFramework.DinosaursParkMes.ProductionPlanning.Dto;
using AppFramework.Migrations;
using AutoMapper;
using Castle.MicroKernel.Util;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Snowflake.Core;
using System.Threading.Tasks;
using PayPalCheckoutSdk.Orders;
using Abp.Application.Services.Dto;
using AppFramework.DinosaursParkMes.Material.Dto;
using Microsoft.EntityFrameworkCore;
using AppFramework.DinosaursParkMes.BOM;
using System.Collections;
using AppFramework.DinosaursParkMes.CodingRuleModel;
using AppFramework.DinosaursParkMes.DomainService.CodingRule;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Abp.Specifications;
using Castle.MicroKernel.SubSystems.Conversion;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using AppFramework.DinosaursParkMes.ProductionPlanningModel;
using AppFramework.DinosaursParkMes.ProductWork.Dto;
using NUglify.Helpers;
using Minio.DataModel;
using Twilio.TwiML.Voice;
using NPOI.SS.Formula.Functions;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
using NPOI.Util;
using System.Runtime.Intrinsics.X86;
using Microsoft.EntityFrameworkCore.Infrastructure;

namespace AppFramework.DinosaursParkMes.ProductionPlanning
{
    public class ProductionPlanningAppService : AppFrameworkAppServiceBase, IProductionPlanningAppService
    {
        private readonly IRepository<Productinfo> productinfo;
        private readonly IRepository<AppFramework.DinosaursParkMes.ProductionPlanningModel.ProductionPlanning> productionplanning;
        private readonly IRepository<MaterialModel.MaterialProductImg> materialproductimg;
        private readonly IRepository<BillOfMaterial> BillOfMaterial;
        private readonly IRepository<BillOfMaterialDetails> billOfMaterialDetails;
        private readonly IRepository<AppFramework.DinosaursParkMes.MaterialModel.Material> material;
        private readonly IRepository<ProductWorkModels> productWorkModels;
        private readonly ICodingruleManager _manager;
        public ProductionPlanningAppService(IRepository<Productinfo> productinfo, IRepository<ProductionPlanningModel.ProductionPlanning> productionplanning, IRepository<MaterialProductImg> materialproductimg, IRepository<BillOfMaterial> billOfMaterial, IRepository<BillOfMaterialDetails> billOfMaterialDetails, IRepository<MaterialModel.Material> material, IRepository<ProductWorkModels> productWorkModels, ICodingruleManager manager)
        {
            this.productinfo = productinfo;
            this.productionplanning = productionplanning;
            this.materialproductimg = materialproductimg;
            BillOfMaterial = billOfMaterial;
            this.billOfMaterialDetails = billOfMaterialDetails;
            this.material = material;
            this.productWorkModels = productWorkModels;
            _manager = manager;
        }
        //[HttpGet,Route("Show")]
        //public dynamic Show()
        //{
        //    string sql = "select * from tb_material";
        //  var lsit=material.Query<MaterialModel.Material>(sql);
        //    return lsit;
        //}
        /// <summary>
        /// 新增生产计划
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [UnitOfWork]
        [HttpPost, Route("AddProductionPlanning")]
        public async Task<AddProductionPlanningDto> AddProductionPlanning([FromBody] AddProductionPlanningDto dto)
        {
            var ProductionPlanningModel = ObjectMapper.Map<AppFramework.DinosaursParkMes.ProductionPlanningModel.ProductionPlanning>(dto);
            ProductionPlanningModel.Planningnumber = await _manager.GetCode("ProductionPlanning");
            await productionplanning.InsertAsync(ProductionPlanningModel);
            foreach (var item in dto.AccessoryChildren)
            {
                var MaterialProductImgmodel = ObjectMapper.Map<MaterialProductImg>(item);
                MaterialProductImgmodel.Number = ProductionPlanningModel.Planningnumber;
                await materialproductimg.InsertAsync(MaterialProductImgmodel);
            }
            return dto;
        }
        /// <summary>
        /// 创建工单
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        [HttpGet, Route("CreateWorkOrder")]
        public async Task<int> CreateWorkOrder(string id)
        {
            //产品
            var productinfolist = await productinfo.GetAll().AsNoTracking().ToListAsync();
            //生产计划
            var ProductionPlanning = await productionplanning.GetAll().AsNoTracking().ToListAsync();
            //BOM详情
            var billOfMaterial = await billOfMaterialDetails.GetAll().AsNoTracking().ToListAsync();
            //查询生产计划
            var DetailsProductionPlanning = ProductionPlanning.Where(x => x.Planningnumber.Equals(id)).FirstOrDefault();
            var BOMdetails = billOfMaterial.Where(x => x.Numberbom.Equals(DetailsProductionPlanning.BOMNumber)).ToList();
            foreach (var item in BOMdetails)
            {
                //查询BOM下关联的产品
                var productinfo = productinfolist.Where(x => x.Productid.Equals(item.Materialnumber)).FirstOrDefault();
                if (productinfo != null)
                {
                    ProductWorkModels productworkModels = new ProductWorkModels()
                    {
                        ExplainNumber = id,
                        WorkOrderNumber = await _manager.GetCode("ProductWorkModels"),
                        WorkOrderName = productinfo.Productname + "工单",
                        WorkOrderSchedule = "0",
                        RelevanceExplain = DetailsProductionPlanning.Planningname,
                        ProductName = productinfo.Productname,
                        ProductNumber = productinfo.Productid,
                        Specification = productinfo.Specification,
                        ProductType = productinfo.Producttype,
                        Unit = productinfo.Units,
                        ExplainNum = DetailsProductionPlanning.Planningcount,
                        AccomplishNum = DetailsProductionPlanning.Planningcount - 1,
                        DemandDate = DetailsProductionPlanning.Demanddate,
                        ExplainStartDate = DetailsProductionPlanning.Starttime,
                        ExplainEndDate = DetailsProductionPlanning.Timeofcompletion,
                        PracticalStartDate = DetailsProductionPlanning.Starttime,
                        PracticalEndDate = DetailsProductionPlanning.Timeofcompletion,
                        Remark = productinfo.Remark,
                        State = ProductState.WaitScheduled
                    };
                    await productWorkModels.InsertAsync(productworkModels);
                }
            }
            DetailsProductionPlanning.State = ProductionPlanState.Decomposed;
            await productionplanning.UpdateAsync(DetailsProductionPlanning);
            return 1;
        }
        /// <summary>
        /// 生产计划详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet, Route("DetailsProductionPlanning")]
        public async Task<DetailsProductionPlanningDTO> DetailsProductionPlanning(string id)
        {
            //物料清单
            var BillOfMateriallist = await BillOfMaterial.GetAll().ToListAsync();
            //物料
            var materiallist = await material.GetAll().ToListAsync();
            //产品
            var productinfolist = await productinfo.GetAll().ToListAsync();
            //BOM详情
            var billOfMaterial = await billOfMaterialDetails.GetAll().ToListAsync();
            //生产计划
            var DetailsProductionPlanning = productionplanning.GetAll().Where(x => x.Planningnumber.Equals(id)).FirstOrDefault();
            //映射生产计划信息
            var model = ObjectMapper.Map<DetailsProductionPlanningDTO>(DetailsProductionPlanning);
            //查询生产计划状态
            var name = model.State;
            switch (name)
            {
                case "UnDecomposed":
                    model.State = "待分解";
                    break;
                case "Decomposed":
                    model.State = "已分解/";
                    break;
                case "UnderWay":
                    model.State = "进行中/";
                    break;
                case "Finished":
                    model.State = "已完成/";
                    break;
                case "Closed":
                    model.State = "已关闭/";
                    break;
                case "WithDrawn":
                    model.State = "已撤回/";
                    break;
            }
            //查询BOM版本
            model.Versionnumber = BillOfMateriallist.Where(x => x.Numberbom.Equals(model.BOMNumber)).FirstOrDefault().Versionnumber;
            //映射生产计划附件信息
            model.AccessoryChildren = ObjectMapper.Map<List<ProductionPlanningAccessory>>(materialproductimg.GetAll().Where(x => x.Number == id));
            //查询BOM详情
            var billOfMaterialDetailsModel = billOfMaterial.Where(s => s.Numberbom.Equals(model.BOMNumber));
            var list1 = new List<MaterialProductMessage>();
            var list2 = new List<MaterialMessage>();
            var list3 = new List<ProductMessage>();
            var list4 = new List<WorkOrderMessage>();

         
            var productinfoS = productinfolist.Where(x => x.Productid.Equals(BillOfMateriallist.Where(x => x.Numberbom.Equals(model.BOMNumber)).FirstOrDefault().Productnumber)).FirstOrDefault();
            list1.Add ( ObjectMapper.Map<MaterialProductMessage>(productinfoS));
            list1[0].Numberbom = model.BOMNumber;
            list1[0].Versionnumber = model.Versionnumber;
            list1[0].Usageamount = 50;
            list1[0].Useratio = 40;
            list1[0].children = new List<MaterialProductMessage>();

            foreach (var item in billOfMaterialDetailsModel)
            {
                var sss = new MaterialProductMessage();
                var kkk = new MaterialMessage();
                var xxx = new ProductMessage();
                //查询BOM下关联的物料
                var materi = materiallist.Where(x => x.Materialnumber.Equals(item.Materialnumber)).FirstOrDefault();
                //查询BOM下关联的产品
                var productinfo = productinfolist.Where(x => x.Productid.Equals(item.Materialnumber)).FirstOrDefault();
                if (materi != null)
                {
                    sss.Numberbom = item.Numberbom;
                    sss.Productname = materi.Name;
                    sss.Productid = materi.Materialnumber;
                    sss.Versionnumber = model.Versionnumber;
                    sss.Usageamount = item.Usageamount;
                    sss.Useratio = item.Useratio;
                    sss.Specification = materi.Specificationsversion;
                    sss.Units = materi.Unit;
                    kkk = ObjectMapper.Map<MaterialMessage>(materi);
                    kkk.Usageamount = item.Usageamount;
                    kkk.PracticalUsageamount = item.Usageamount - 1;
                    list2.Add(kkk);
                    list1[0].children.Add(sss);
                }
                if (productinfo != null)
                {
                    sss = ObjectMapper.Map<MaterialProductMessage>(productinfo);
                    sss.Numberbom = item.Numberbom;
                    sss.Versionnumber = model.Versionnumber;
                    sss.Usageamount = item.Usageamount;
                    sss.Useratio = item.Useratio;
                    xxx = ObjectMapper.Map<ProductMessage>(productinfo);
                    xxx.Usageamount = item.Usageamount;
                    xxx.PracticalUsageamount = item.Usageamount - 1;
                    list3.Add(xxx);
                    list1[0].children.Add(sss);
                }
            }
            //生产工单 详情
            List<WorkOrderMessage> productWorks = ObjectMapper.Map<List<WorkOrderMessage>>(productWorkModels.GetAll().Where(x => x.ExplainNumber == id));
            productWorks.ForEach(x =>
            {
                switch (x.State)
                {
                    case "WaitScheduled":
                        x.State = "待排产";
                        break;
                    case "NotStarted":
                        x.State = "未开始/";
                        break;
                    case "InProgress":
                        x.State = "进行中/";
                        break;
                    case "Completed":
                        x.State = "已完成/";
                        break;
                    case "Paused":
                        x.State = "已暂停/";
                        break;
                    case "Closed":
                        x.State = "已关闭/";
                        break;
                }
            });
            model.MaterialProductChildren = list1;
            model.MaterialChildren = list2;
            model.ProductChildren = list3;
            model.WorkOrderChildren = productWorks;
            return model;
        }
        /// <summary>
        /// 生产计划列表
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet, Route("ShowProductionPlanning")]
        public async Task<PagedResultDto<ShowProductionPlanningDto>> ShowProductionPlanning(ProductionPlanninglSelectDTO dto)
        {
            var res = new PagedResultDto<ShowProductionPlanningDto>();
            var list = ObjectMapper.Map<List<ShowProductionPlanningDto>>(productionplanning.GetAll());
            list.ForEach(item =>
            {
                item.WorkOrderCount = 3;
                var name = item.State;
                switch (name)
                {
                    case "UnDecomposed":
                        item.State = "待分解";
                        break;
                    case "Decomposed":
                        item.State = "已分解/";
                        break;
                    case "UnderWay":
                        item.State = "进行中/";
                        break;
                    case "Finished":
                        item.State = "已完成/";
                        break;
                    case "Closed":
                        item.State = "已关闭/";
                        break;
                    case "WithDrawn":
                        item.State = "已撤回/";
                        break;
                }
            });
            var data = from x in list
                       where (string.IsNullOrEmpty(dto.Name) || dto.Name == x.Planningnumber || dto.Name == x.Planningname)
                        && (string.IsNullOrEmpty(dto.Sourcetype) || dto.Sourcetype == x.Sourcetype)
                        && (string.IsNullOrEmpty(dto.Finishedname) || dto.Finishedname == x.Finishedname)
                        && (string.IsNullOrEmpty(dto.State) || dto.State == x.State)
                        && (default(DateTime) == dto.Starttime || dto.Starttime < x.Starttime)
                        && (default(DateTime) == dto.Endtime || dto.Endtime.AddDays(1) > x.Starttime)
                       && (default(DateTime) == dto.Timeofcompletion || dto.Timeofcompletion < x.Timeofcompletion)
                       && (default(DateTime) == dto.EndTimeofcompletion || dto.EndTimeofcompletion.AddDays(1) > x.Timeofcompletion)
                       && (default(DateTime) == dto.Demanddate || dto.Demanddate < x.Demanddate)
                       && (default(DateTime) == dto.EndDemanddate || dto.EndDemanddate.AddDays(1) > x.Demanddate)
                       select x;
            res.Items = data.OrderByDescending(x => x.Starttime).Skip((dto.PageIndex - 1) * dto.PageSize).Take(dto.PageSize).ToList();
            res.TotalCount = res.Items.Count();
            return res;
        }
    }
}
